package social.hub.oauth.scribe;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

import social.hub.oauth.OAuthServiceConfig;
import social.hub.oauth.OAuthToken;
import social.hub.oauth.OAuthServiceConfig.OAuthVersion;
import social.hub.oauth.scribe.ScribeServiceProvider;
import social.hub.util.Utils;

public class ITScribeServiceProvider_OAuth2 {

	private ScribeServiceProvider provider;
	private OAuthServiceConfig serviceConfig;

	@Before
	public void setUp() throws Exception {

		serviceConfig = new OAuthServiceConfig();

		serviceConfig.setAuthorizeUrl("https://www.facebook.com/dialog/oauth?"
				+ "client_id={appId}&redirect_uri={callbackUrl}&scope=publish_stream");
		serviceConfig
				.setAccessTokenUrl("https://graph.facebook.com/oauth/access_token?"
						+ "client_id={appId}&redirect_uri={callbackUrl}&client_secret={apiSecret}&code={code}");

		serviceConfig.setAppId("129640830439428");
		serviceConfig.setApiKey("23ed5917c0e12da0f116683d6c275cdf");
		serviceConfig.setApiSecret("e48510f3872d2a81810db6649f9b93f0");
		serviceConfig.setCallbackUrl("http://www.amigon.com.br/requestCallback");

		serviceConfig.setVersion(OAuthVersion.V_2);

		provider = new ScribeServiceProvider(serviceConfig);

	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testGetAccessToken() throws IOException {

		WebDriver driver = new FirefoxDriver();

		String username = "usuarioteste1@ymail.com";
		String password = "senhateste1";

		// autorizar manualmente no browser...
		String authorizationUrl = provider.getAuthorizationUrl(null);

		driver.get(authorizationUrl);

		WebElement usernameInput = driver.findElement(By.id("email"));
		usernameInput.sendKeys(username);

		WebElement passwordInput = driver.findElement(By.id("pass"));
		passwordInput.sendKeys(password);

		usernameInput.submit();

		String resultUrl = driver.getCurrentUrl();

		// se ja não autorizou
		if (!resultUrl.startsWith(serviceConfig.getCallbackUrl())) {

			WebElement allowSubmit = driver.findElement(By.name("grant_clicked"));

			allowSubmit.click();

			resultUrl = driver.getCurrentUrl();

		}

		Map<String, String> parans = montarParametros(resultUrl);

		OAuthToken accessToken = provider.getAccessToken(null, parans);

		assertNotNull(accessToken);
		assertNotNull(accessToken.getToken());
		assertNotNull(accessToken.getSecret());

		driver.close();

	}

	@Test
	public void testGetAuthorizationUrl() {

		String callbackUrl = serviceConfig.getCallbackUrl();
		String appId = serviceConfig.getAppId();

		String expectedUrl = "https://www.facebook.com/dialog/oauth?" + "client_id="
				+ Utils.encode(appId) + "&redirect_uri=" + Utils.encode(callbackUrl)
				+ "&scope=publish_stream";
		String authorizationUrl = provider.getAuthorizationUrl(null);

		assertEquals(expectedUrl, authorizationUrl);

	}

	@Test
	public void testGetRequestToken() {

		OAuthToken requestToken = provider.getRequestToken();

		assertNull(requestToken);

	}

	@Test
	public void testGetServiceConfig() {

		OAuthServiceConfig result = provider.getServiceConfig();

		assertSame(serviceConfig, result);

	}

	private Map<String, String> montarParametros(String resultUrl) {

		Map<String, String> parans = new HashMap<String, String>();

		String queryString = resultUrl.substring(resultUrl.indexOf("?") + 1, resultUrl.length());

		String[] strings = queryString.split("&");

		for (String string : strings) {
			String[] paran = string.split("=");
			String key = paran[0];
			String value = paran[1];
			parans.put(key, value);
		}

		return parans;

	}

}
